%option noyywrap
%option nounput
%option noinput
%top{
    #include <stdarg.h>
    #include "common.h"

        // #define ONLY_FOR_LEX //条件编译
    
    #ifdef ONLY_FOR_LEX //条件编译
    #else // 主要用于lex和yacc文件之间的信息传递

    #include "parser.h"
    #endif

}
%{
    // extern dump_type_t dump_type;


    #include <string>
    #include <vector>
    #ifdef ONLY_FOR_LEX
    #include <ostream>
    #include <fstream>
    #include <iostream>
    #include <math.h>
    using namespace std;
    extern FILE *yyin; 
    extern FILE *yyout;


    // 词法分析器的输出流测试lab1
    void dump_tokens(std::string s, const char *yytext) {
        string a = yytext;
        // cout << a << endl;
        std::string DEBUG_INFO = "[DEBUG LAB1]: \t" + s + a + "\t" + "lineNO:" + to_string(yylineno) +"\n";
        
        fputs(DEBUG_INFO.c_str(), yyout);
    }
    #endif

    /* TODO: 初始化词法分析器的其他全局变量或状态信息 */
%}

/* definitions section */
DECIMIAL ([1-9][0-9]*|0) 
ID [[:alpha:]_][[:alpha:][:digit:]_]*
char ('.')
SPACE " "
linecomment (\/\/.*|\/\/.*)
commentbegin "/*"
commentelement .|\n
commentend "*/"
EOL (\r\n|\n|\r)
WHITE [\t ]


/*一行注释*/
EXEGESIS ("//".*{EOL})

/*多行注释*/
EXEGESIS2 ("/*"(.|\n)*?"*/")
/* TODO: 定义其他正则表达式或宏，用于匹配更多的词法单元 */

%%
    /* rules section */

    /*数据类型*/
"int" {
    #ifdef ONLY_FOR_LEX 
        dump_tokens("INT\t", yytext);
    #else
        return INT;
    #endif
}



    /*主函数声明*/
"main" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("MAIN\t", yytext);
    #else
        return MAIN;
    #endif
}


    /*条件控制语句*/
"if" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("IF\t", yytext);
    #else
        return IF;
    #endif
}

"else" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("ELSE\t", yytext);
    #else
        return ELSE;
    #endif
}

    /*循环控制语句*/
"while" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("WHILE\t", yytext);
    #else
        return WHILE;
    #endif
}

"for" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("FOR\t", yytext);
    #else
        return FOR; 
    #endif
}

"break" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("BREAK\t", yytext);
    #else
        return BREAK;
    #endif
}

"continue" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("CONTINUE\t", yytext);
    #else
        return CONTINUE;
    #endif
}





    /*函数定义*/

"return" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("RETURN\t", yytext);
    #else
        return RETURN;
    #endif
}


    /*运算符*/

"&&" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("AND\t", yytext);
    #else
        return AND;
    #endif
}

"||" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("OR\t", yytext);
    #else
        return OR;
    #endif
}

"!" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("NOT\t", yytext);
    #else
        return NOT;
    #endif
}

"=" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("ASSIGN\t", yytext);
    #else
        return ASSIGN;
    #endif
}

"==" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("EQUAL\t", yytext);
    #else
        return EQ;
    #endif
}

"!" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("NOT\t", yytext);
    #else
        return NOT;
    #endif
}

"!=" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("UNEQUAL\t", yytext);
    #else
        return NEQ;
    #endif
}



"<" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("LESS\t", yytext);
    #else
        return LESS;
    #endif
}

"<=" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("LESSEQUAL\t", yytext);
    #else
        return LEQ;
    #endif
}


">" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("MORE\t", yytext);
    #else
        return GREATER;
    #endif
}

">=" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("MOREEQUAL\t", yytext);
    #else
        return GEQ;
    #endif
}

"++" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("SELFADD\t", yytext);
    #else
        return SELFADD;
    #endif
}

"--" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("SELFDEC\t", yytext);
    #else
        return SELFDEC;
    #endif
}

"+" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("ADD\t", yytext);
    #else
        return ADD;
    #endif
}

"-" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("SUB\t", yytext);
    #else
        return SUB;
    #endif
}

"*" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("MUL\t", yytext);
    #else
        return MUL;
    #endif
}

"/" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("DIV\t", yytext);
    #else
        return DIV;
    #endif
}

"%" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("MOD\t", yytext);
    #else
        return MOD;
    #endif
}

    /*逗号、冒号、分号、引号、括号*/

"," {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("COMMA\t", yytext);
    #else
        return COMMA;
    #endif
}

":" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("COLON\t", yytext);
    #else
        return COLON;
    #endif
}



";" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("SEMICOLON\t", yytext);
    #else
        return SEMICOLON;
    #endif
}



"(" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("LP\t", yytext);
    #else
        return LP;
    #endif
}

")" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("RP\t", yytext);
    #else
        return RP;
    #endif
}

"{" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("LB\t", yytext);
    #else
        return LB;
    #endif
}

"}" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("RB\t", yytext);
    #else
        return RB;
    #endif
}

"scanf" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("SCAN\t", yytext);
    #else
        return SCAN;
    #endif
}

"printf" {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("PRINT\t", yytext);
    #else
        return PRINT;
    #endif
}





{DECIMIAL} {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("DECIMIAL\t", yytext);
    #else
        yylval.itype = atoi(yytext);
        return INTEGER;
    #endif
}

{EXEGESIS2} {
    // 识别注释
    // printf("多行注释\t", yytext);
}

{EXEGESIS} {
    // 识别注释
    // dump_tokens("注释\t", yytext);
    // printf("注释\t", yytext);
}

{ID} {
    #ifdef ONLY_FOR_LEX        
        dump_tokens("ID\t", yytext);
    #else
        char *lexeme;
        lexeme = new char[strlen(yytext) + 1];
        strcpy(lexeme, yytext);
        yylval.strtype = lexeme;
        // printf("yytext: %s\n", yytext);
        return ID;
    #endif
}

{EOL} yylineno++;

{WHITE}



%%


    /* lab1调试主窗口 */
#ifdef ONLY_FOR_LEX
int main(int argc, char **argv){
    if(argc != 5){
        fprintf(stderr, "Argument Not Enough");
        exit(EXIT_FAILURE);
    }

    if(!(yyin = fopen(argv[1], "r"))){
        fprintf(stderr, "No such file or directory: %s", argv[1]);
        exit(EXIT_FAILURE);
    }

    if(!(yyout = fopen(argv[3], "w"))){
        fprintf(stderr, "No such file or directory: %s", argv[3]);
        exit(EXIT_FAILURE);
    }

    yylex();
    return 0;
}
#endif